package com.jpemartin.jgt;
import java.util.*;

/**
 *  The UnionIterator combines iterator to creates a single new iterator
 *  that goes through each iterator in the list.
 *  
 *  Unlike Iterator, here you have to indicate which type is iterated over
 *  (it's optional for Iterator). Here's an example:
 *  
 *  UnionIterator<VisibleObject> tots = new UnionIterator<VisibleObject>(goodGuys,badGuys);
 *  
 *  @author jpmartin
 */
public class UnionIterator<T> implements Iterator<T> {
   
   protected List<Iterator<T>> _iterators;
   
   /** Give several iterators to the ctor, and you get an iterator that goes
    * through all the iterators you gave.
    */
   public UnionIterator(Iterator<T>... iterators) {
      //_iterators = new ArrayList<Iterator<T>>();
      //_iterators.addAll(Arrays.asList(iterators));
      _iterators = Arrays.asList(iterators);
   }
   
   /** Give several collections to the ctor, and you get an iterator that goes
    * through all the collections you gave.
    */
   public UnionIterator(Iterable<T>... collections) {
      _iterators = new ArrayList<Iterator<T>>();
      for (int i=0; i<collections.length; i++)
         _iterators.add(collections[i].iterator());
   }
   
   public boolean hasNext() {
      boolean aux;
      do {
         if (0==_iterators.size()) return false;
         // repeat until the iterator is non-empty
         aux = _iterators.get(0).hasNext();
         if (!aux) _iterators.remove(0);
      } while (!aux);
      // we have an iterator with at least one element
      return true;
   }
   
   public T next() {
      // we call hasNext to move on to the next iterator if necessary
      // (the user might not call hasNext)
      if (!hasNext()) throw new NoSuchElementException("There are no more elements in any Iterator in the UnionIterator");
      // hasNext returned true, so we know _iterators.get(0) is non-null
      return _iterators.get(0).next();
   }
   
   public void remove() {
      // we don't call hasNext, because we may have to call remove()
      // even on an iterator that has no more elements.
      _iterators.get(0).remove();        
   }
   
   
}
